package MVC.Controllers;

import MVC.Controller;
import MVC.Models.Jogador;
import MVC.Models.LancePosicao;
import MVC.Models.LanceRotacao;
import MVC.Models.Tabuleiro;
import Resources.Enums.Cor;
import br.ufsc.inf.leobr.cliente.*;
import br.ufsc.inf.leobr.cliente.exception.*;

public class NetGamesController extends Controller implements OuvidorProxy {

    /* Attributos */
    private Proxy proxy = Proxy.getInstance();

    public NetGamesController() {
        proxy.addOuvinte(this);
    }

    /* Actions */
    public boolean conectar(String nome, String servidor) {
        try {
            proxy.conectar(servidor, nome);
            return true;
        } catch (JahConectadoException e) {
            jogadorController.getApplicationView().alert(e.getMessage());
            return false;
        } catch (NaoPossivelConectarException e) {
            jogadorController.getApplicationView().alert(e.getMessage());
            return false;
        } catch (ArquivoMultiplayerException e) {
            jogadorController.getApplicationView().alert(e.getMessage());
            return false;
        }
    }

    public boolean desconectar() {
        try {
            proxy.desconectar();
            return true;
        } catch (NaoConectadoException e) {
            jogadorController.getTabuleiroView().alert(e.getMessage());
            return false;
        }
    }

    public void iniciarPartida() {
        try {
            proxy.iniciarPartida(2);
        } catch (NaoConectadoException e) {
            jogadorController.getTabuleiroView().alert(e.getMessage());
        }
    }

    public void reiniciarPartida() {
        try {
            proxy.reiniciarPartida();
        } catch (NaoConectadoException e) {
            jogadorController.getTabuleiroView().alert(e.getMessage());
        } catch (NaoJogandoException e) {
            jogadorController.getTabuleiroView().alert(e.getMessage());
        }
    }

    public void enviarLance(Jogada jogada) {
        try {
            proxy.enviaJogada(jogada);
        } catch (NaoJogandoException e) {
            jogadorController.getTabuleiroView().alert(e.getMessage());
        }
    }

    public void iniciarNovaPartida(Integer numeroJogador) {
        Integer numeroOponente = (numeroJogador == 1) ? 2 : 1;

        Tabuleiro tabuleiro = jogadorController.getTabuleiro();
        tabuleiro.setConectado(true);
        tabuleiro.esvaziar();

        Jogador jogador = tabuleiro.getJogador();
        jogador.parar();

        Jogador oponente = new Jogador(proxy.obterNomeAdversarios().get(0));
        tabuleiro.setOponente(oponente);

        tabuleiro.prepararJogador(numeroJogador, true);
        tabuleiro.prepararJogador(numeroOponente, false);

        tabuleiro.setEmAndamento(true);
        tabuleiro.sortear();

        jogadorController.getTabuleiroView().refresh();
    }

    public void finalizarPartidaComErro(String s) {
        Tabuleiro tabuleiro = jogadorController.getTabuleiro();

        if (tabuleiro.getEmAndamento())
            jogadorController.getTabuleiroView().alert(s);

        Jogador jogador = tabuleiro.getJogador();
        jogador.parar();

        tabuleiro.setOponente(null);
        tabuleiro.setConectado(false);
        tabuleiro.esvaziar();

        jogadorController.getTabuleiroView().refresh();
    }

    public void receberMensagem(String s) {
        jogadorController.getTabuleiroView().alert(s);
    }

    public void receberJogada(Jogada jogada) {
        Tabuleiro tabuleiro = jogadorController.getTabuleiro();

        if (jogada instanceof LancePosicao) {
            LancePosicao lancePosicao = (LancePosicao) jogada;
            tabuleiro.inserirPeca(lancePosicao.getLinha(), lancePosicao.getColuna());
        } else if (jogada instanceof LanceRotacao) {
            LanceRotacao lanceRotacao = (LanceRotacao) jogada;
            tabuleiro.realizarRotacao(lanceRotacao.getQuadrante(), lanceRotacao.getHorario());
        }

        Cor cor = tabuleiro.tratarLance();
            if (cor != null)
                tabuleiro.definirVencedor(cor);
            else {
                boolean cheio = tabuleiro.tratarTabuleiroCheio();
                if (cheio)
                    tabuleiro.definirEmpate();
                else if (jogada instanceof LanceRotacao)
                    tabuleiro.proximoJogador();
            }

        jogadorController.getTabuleiroView().refresh();
    }

    public void tratarConexaoPerdida() {
        jogadorController.getTabuleiroView().alert("Conexão perdida");
    }

    public void tratarPartidaNaoIniciada(String s) {
        jogadorController.getTabuleiroView().alert("Partida não iniciada");
    }

}
